﻿namespace PrismEx.Events
{
    using System;
    using System.Diagnostics.Contracts;

    using Microsoft.Practices.Prism.Events;

    /// <summary>
    /// Extension methods for IEventAggregator
    /// </summary>
    public static class EventAggregatorExtensions
    {
        /// <summary>
        /// Publishes the event through the event aggregator
        /// </summary>
        /// <typeparam name="TEventType">Type of the event</typeparam>
        /// <param name="aggregator">Event Aggregator</param>
        /// <param name="event">Event payload</param>
        public static void Publish<TEventType>(this IEventAggregator aggregator, TEventType @event) where TEventType : CompositePresentationEvent<TEventType>, new()
        {
            aggregator.Publish<TEventType, TEventType>(@event);
        }

        /// <summary>
        /// Publishes an event where the payload is not important, just the occurence of the event is important
        /// </summary>
        /// <typeparam name="TEventType">Type of event to be published</typeparam>
        /// <param name="aggregator">Event Aggregator</param>
        public static void Publish<TEventType>(this IEventAggregator aggregator) where TEventType : CompositePresentationEvent<TEventType>, new()
        {
            aggregator.Publish<TEventType, TEventType>(default(TEventType));
        }

        /// <summary>
        /// Publishes an event through the event aggregator
        /// </summary>
        /// <typeparam name="TEventType">Type of event to be published</typeparam>
        /// <typeparam name="TPayload">Type of the payload</typeparam>
        /// <param name="aggregator">Event Aggregator</param>
        /// <param name="payload">The payload for the event</param>
        public static void Publish<TEventType, TPayload>(this IEventAggregator aggregator, TPayload payload) where TEventType : CompositePresentationEvent<TPayload>, new()
        {
            if (null == aggregator)
            {
                return;
            }

            var message = aggregator.GetEvent<TEventType>();

            if (null == message)
            {
                return;
            }

            message.Publish(payload);
        }

        /// <summary>
        /// Subscribes to an event with the supplied delegate
        /// </summary>
        /// <typeparam name="TEventType">Type of event to be published</typeparam>
        /// <param name="aggregator">Event Aggregator</param>
        /// <param name="action">Delegate called when the event is published</param>
        /// <returns>A token used to manage the subscription</returns>
        public static SubscriptionToken Subscribe<TEventType>(this IEventAggregator aggregator, Action<TEventType> action) where TEventType : CompositePresentationEvent<TEventType>, new()
        {
            return aggregator.Subscribe<TEventType, TEventType>(action);
        }

        /// <summary>
        /// Subscribes to an event with the supplied delegate
        /// </summary>
        /// <typeparam name="TEventType">Type of event to be published</typeparam>
        /// <typeparam name="TPayload"></typeparam>
        /// <param name="aggregator">Event Aggregator</param>
        /// <param name="action">Delegate called when the event is published</param>
        /// <returns>A token used to manage the subscription</returns>
        /// <returns>A token used to manage the subscription</returns>
        public static SubscriptionToken Subscribe<TEventType, TPayload>(this IEventAggregator aggregator, Action<TPayload> action) where TEventType : CompositePresentationEvent<TPayload>, new()
        {
            var @event = aggregator.GetEvent<TEventType>();

            return null == @event ? null : @event.Subscribe(action);
        }
    }
}